# -*- coding: utf-8 -*-

import logging
import sys
import threading
import traceback
import uuid
from concurrent.futures import Executor, ThreadPoolExecutor
from threading import current_thread
from logging import handlers, Handler, Filter, Formatter, LogRecord
from queue import Queue
from time import sleep

logger = logging.getLogger(__name__)

log_fmt = '%(asctime)s.%(msecs)03d %(levelname)8s %(funcName)16s:%(lineno)3d %(message)s'
thread_local_name = 'NAME'


class ThreadLocal(object):

    def __init__(self):
        self.__storage = threading.local()

    def hasattr(self, key, ):
        return hasattr(self.__storage, key)

    def get_attr(self, key, default=None):
        if hasattr(self.__storage, key):
            return getattr(self.__storage, key)
        else:
            return default

    def set_attr(self, key, value):
        setattr(self.__storage, key, value)

    def del_attr(self, key):
        if hasattr(self.__storage, key):
            return delattr(self.__storage, key)
        pass


thread_local = ThreadLocal()


class CustomHandler(Handler):
    """自定义Handler"""

    def __init__(self):
        Handler.__init__(self)

    def emit(self, record: LogRecord):
        # print(vars(record))
        print(record.threadName, end=' ')
        if hasattr(record, thread_local_name):
            thread_local_data = getattr(record, thread_local_name)
            if thread_local_data:
                print(f'{thread_local_name}:{thread_local_data}', end=' ')
        if record.exc_info:
            # 使用traceback模块来格式化并打印异常信息
            exc_type, exc_value, exc_traceback = record.exc_info
            tb_lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
            tb_str = ''.join(tb_lines)
            print(tb_str)
        print(f'msg:{record.getMessage()}')
        pass


class CustomFilter(Filter):

    # def __init__(self, name=''):
    #     super().__init__(name)

    def filter(self, record):
        thread_local_data = 'null'
        if thread_local.hasattr(thread_local_name):
            thread_local_data = thread_local.get_attr(thread_local_name)
        setattr(record, thread_local_name, thread_local_data)
        return True


class TaskBase:

    def __init__(self, task_name):
        self.name = task_name
        logger.info(f'task:{self.name} init')

    def run(self):
        logger.info('run start')
        logger.info(f'task name:{self.name}')
        logger.info(f'run step')
        run_func()
        logger.info('run end')

    pass


def run_func():
    logger.info(f'run_func')


def run_task(task_name):
    logger.info('run_task start')
    thread_local.set_attr(thread_local_name, task_name)
    TaskBase(task_name).run()
    thread_local.del_attr(thread_local_name)
    logger.info('run_task end')
    return 1


def test_logger_handler():
    queue = Queue()
    logger.setLevel(logging.DEBUG)

    queue_handler = handlers.QueueHandler(queue)
    logger.addHandler(queue_handler)

    custom_handler = CustomHandler()
    logger.addHandler(custom_handler)

    custom_filter = CustomFilter()
    custom_handler.addFilter(custom_filter)

    stream_handler = logging.StreamHandler(stream=sys.stderr)
    stream_handler.setFormatter(Formatter(fmt=log_fmt))

    queue_listener = handlers.QueueListener(queue, custom_handler, stream_handler, respect_handler_level=True)
    queue_listener.start()

    logger.info('main start')
    executor: Executor = ThreadPoolExecutor(max_workers=4)
    for i in range(1):
        executor.submit(run_task, f'task-{i}')

    # print(f'result:{future.result()}')

    logger.info('main end')
    executor.shutdown()
    queue_listener.stop()


if __name__ == '__main__':
    test_logger_handler()
